//ShaderManager.h
//Created 01/06/13
//Created By Daniel Bowler
//
//As I am not a huge fan of the method that the book uses to manage
//shaders, input layouts and so on (Its not that it is bad, just not my cup of tea)
//I have decided to explore the option to create some form of shader manager
//that we can use in this project and potentially in the dissertation. I may
//as well explore it now whilst I have plenty of time. 


#pragma once

#include "d3dUtil.h"

//Forward declare graphics manager class - we need access to the device
class GraphicsManager;

//
//General Effects
//
//Forward declare FX classes - Include them in the .cpp. Note that - as a result,
//each scene / object that wants to use them must #include the FX at somepoint
//in its own class.
class TexturedFullScreenQuadFX;
class DebugDrawLightsFX;
class SkyDomeFX;

class TileForwardNormalMapFX;
class TileForwardNormalMapInstFX;
class TileForwardStandardFX;
class TileForwardTextureMapFX;

class TileForwardTextureMapInstFX;
class TileForwardDisplacementMappingFX;
class TileForwardDisplacementMapInstFX;
class TileForwardSolidColourFX;
class TileForwardSolidColourInstFX;

class TileForwardAnimNormalMapFX;
class TileForwardAnimTextureMapFX;
class TileForwardAnimSolidColourFX;

//Advanced effects
class OceanWaveFX;
class TerrainFX;
class TerrainWaterFX;

//POM
class ParallaxOcclusionMappingFX;

//Roo's world specific
class ReflectRefractFX;

//Post Proc / Screen Space effects
class SSAOMapFX;
class SSAOBlurFX;
class SSAOBlurCSFX;

//2D rendering (font/sprites)
class SpriteFX;

//
//Compute Shader Effects
//
//Forward delcare the CS effect for tile based forward rendering - Light Culling Stage.
class TileForwardLightCullCSFX;

class ShaderManager
{
	//Whilst the ShaderManager will create all of our effects, some
	//should NOT be created in such a manner that any random
	//guy can get a pointer to them.
	//
	//Here you can put your friend declarations.
	//
	//Graphics manager will be the class used to preform the z-pre
	//pass.
	friend GraphicsManager;

public:
	//Static function that obtains a reference to the ShaderManager
	static ShaderManager* GetInstance();
	//Release function - called at the end of the apps lifespan by our
	//GraphicsManager
	void Release();

	//Function called when we recreate the Light List Buffer (LLB). This should
	//update the LLB of each tile based forward rendering effect that needs it. 
	//(avoids per frame updates)
	void OnReallocOfLLB(ID3D11ShaderResourceView* llb);
	//Function will be called when a resize event occurs - We can then update our
	//effects.
	void OnResize(unsigned newWidth, unsigned newHeight);

public:
	//PUBLIC Getters for the FX objects -  
	//IE, Demo Scenes can access and use them.
	//
	//Eg, our forward effects used for testing (may get some use later, hence
	//why I am going to keep them in (and it may be useful to demonstrate these
	//in the viva)
	TexturedFullScreenQuadFX* ReturnTexturedFullScreenQuadFX(){return texturedFullScreenQuadFX;};
	SkyDomeFX* ReturnSkyDomeFX(){return skyDomeFX;};

	TileForwardNormalMapFX* ReturnTileForwardNormalMapFX(){return tileForwardNormalMapFX;};
	TileForwardNormalMapInstFX* ReturnTileForwardNormalMapInstFX(){return tileForwardNormalMapInstFX;};
	TileForwardStandardFX* ReturnTileForwardStandardFX(){return tileForwardStandardFX;};
	TileForwardTextureMapFX* ReturnTileForwardTextureMapFX(){return tileForwardTextureMapFX;};
	
	TileForwardTextureMapInstFX* ReturnTileForwardTextureMapInstFX(){return tileForwardTextureMapInstFX;};
	TileForwardDisplacementMappingFX* ReturnTileForwardDisplacementMappingFX(){return tileForwardDisplacementMappingFX;};
	TileForwardDisplacementMapInstFX* ReturnTileForwardDisplacementMapInstFX(){return tileForwardDisplacementMapInstFX;};
	TileForwardSolidColourFX* ReturnTileForwardSolidColourFX(){return tileForwardSolidColourFX;};
	TileForwardSolidColourInstFX* ReturnTileForwardSolidColourInstFX(){return tileForwardSolidColourInstFX;};
	
	TileForwardAnimNormalMapFX* ReturnTileForwardAnimNormalMapFX(){return tileForwardAnimNormalMapFX;};
	TileForwardAnimTextureMapFX* ReturnTileForwardAnimTextureMapFX(){return tileForwardAnimTextureMapFX;};
	TileForwardAnimSolidColourFX* ReturnTileForwardAnimSolidColourFX(){return tileForwardAnimSolidColourFX;};

	OceanWaveFX* ReturnOceanWaveFX(){return oceanWaveFX;};
	TerrainFX* ReturnTerrainFX(){return terrainFX;};
	TerrainWaterFX* RetrunTerrainWaterFX(){return terrainWaterFX;};

	ParallaxOcclusionMappingFX* ReturnPOMFX(){return pomFX;};

	ReflectRefractFX* ReturnReflectRefractFX(){return reflectRefractFX;};

public:
	//Scren space / post proc effects
	SSAOBlurFX* ReturnSSAOBlurFX(){return ssaoBlurFX;};
	SSAOMapFX* ReturnSSAOMapFX(){return ssaoMapFX;};
	SSAOBlurCSFX* ReturnSSAOBlurCSFX(){return ssaoBlurCSFX;};

public:
	//Other
	SpriteFX* ReturnSpriteFX(){return spriteFX;};

private:
	//PRIVATE getters to effects that I dont want those creating a game
	//to get hold of - thus, only the graphics programmer should
	//call these functions. 
	//
	//Remember to make a friend declaration!
	//
	//Graphics manager will be the ONLY class that will be able to access and
	//use the tileForwardLightCulling effect - Preforms the TIle Culling Stage using
	//Direct Compute.
	TileForwardLightCullCSFX* ReturnTileForwardLightCullCSFX(){return tileForwardLightCullCSFX;};
	//The graphics manager will be responsable for rendering lights to the screen
	//if desired. Thus, ensure that any Tom, Dick or Harry can not obtain a pointer
	//to the effect in question.
	DebugDrawLightsFX* ReturnDebugDrawLightsFX(){return debugDrawLightsFX;};

private:
	//*******Shader (effect) pointers******* 
	//Both public and private. Also both Compute FX and Standard FX
	//
	//Standard Effects.
	TileForwardNormalMapFX* tileForwardNormalMapFX;
	TileForwardNormalMapInstFX* tileForwardNormalMapInstFX;
	TileForwardTextureMapFX* tileForwardTextureMapFX;

	TileForwardTextureMapInstFX* tileForwardTextureMapInstFX;
	TileForwardDisplacementMappingFX* tileForwardDisplacementMappingFX;
	TileForwardDisplacementMapInstFX* tileForwardDisplacementMapInstFX;
	TileForwardSolidColourFX* tileForwardSolidColourFX;
	TileForwardSolidColourInstFX* tileForwardSolidColourInstFX;

	TileForwardAnimNormalMapFX *tileForwardAnimNormalMapFX;
	TileForwardAnimTextureMapFX *tileForwardAnimTextureMapFX;
	TileForwardAnimSolidColourFX *tileForwardAnimSolidColourFX;

	//Advanced effects
	OceanWaveFX* oceanWaveFX;
	SkyDomeFX* skyDomeFX;
	TileForwardStandardFX* tileForwardStandardFX;
	TerrainFX* terrainFX;
	TerrainWaterFX* terrainWaterFX;

	//Parallax Occlusion Mapping
	ParallaxOcclusionMappingFX* pomFX;

	//Roo's world specific
	ReflectRefractFX* reflectRefractFX;

	//Other effects. 
	TexturedFullScreenQuadFX* texturedFullScreenQuadFX;
	DebugDrawLightsFX* debugDrawLightsFX;

	//
	//Compute Shader Effects
	//
	//Graphics manager will be the ONLY class that will be able to access and
	//use the tileForwardLightCulling effect.
	TileForwardLightCullCSFX* tileForwardLightCullCSFX;

private:
	//Screen space / post proc effects
	SSAOBlurFX* ssaoBlurFX;
	SSAOMapFX* ssaoMapFX;
	SSAOBlurCSFX* ssaoBlurCSFX;

private:
	//Other
	SpriteFX *spriteFX;

private: 
	//Ensure this class will be a singleton
	ShaderManager();
	~ShaderManager();
	ShaderManager(const ShaderManager& other);
	ShaderManager& operator = (const ShaderManager& other);
	//Static instance that we will return when other classes request
	//a reference to this class. 
	static ShaderManager* instance;

	//Inits all of our effects. (CS == Compute Shader)
	void InitStandardEffects(ID3D11Device* device);
	void InitCSEffects(ID3D11Device* device);
};